04 - Layout/02 - Layout Components.js (40 lines of code) (raw):
// Layout System Example Components
// The Vertical List can layout items in vertically based on their dynamic
// height. It also provides its own total height so that it can be used as
// an item within itself.
class VerticalList {
getChildContext() {
return {
layoutWidth: this.props.width || this.context.layoutWidth
};
}
// NEW FEATURE: Pre-render a subtree before continuing with the normal render.
preRender() {
// Children that needs to be prerendered. If some children needs to be
// prerendered, but not others (e.g. for flexbox layouts), then they're
// filtered, here and the rest is rendered inside render.
return this.props.children;
}
render() {
var children = this.prerendered;
var positionedChildren = [];
var y = 0;
for (var i = 0; i < children.length; i++) {
// This child is an opaque black box whose props cannot be inspected,
// nor cloned. It can only be rendered once. Rendering it twice results
// in a conflict, at least until we support painting the same stateful
// component in many different places (e.g. SVG's <use />)
var child = children[i];
positionedChildren.push(
<Positioner key={child.key} x={0} y={y}>{child}</Positioner>
);
// We can use it to inspect the child's reverse context though.
y += child.result.layoutHeight;
}
return <Fragment>{positionedChildren}</Fragment>;
}
// NEW FEATURE: When a component itself is is prerendered, it can bubble a
// result back up the tree.
getResult() {
// We already had this height calculated in render, but to allow for render
// to be deferred, and to preserve the standard render() API, we have to
// recalculate it here. This is helpful in the cases where a parent decides
// not to render this child. That way we can avoid calling render.
var totalHeight = 0;
var children = this.prerendered;
for (var i = 0; i < children.length; i++) {
totalHeight += children[i].result.layoutHeight;
}
return {
layoutHeight: totalHeight
};
}
}
class VerticalListItem {
render() {
return (
<Box width={this.context.layoutWidth} height={this.props.height}>
{this.props.children}
</Box>
);
}
getResult() {
return {
layoutHeight: this.props.height
};
}
}